package belf.migrate.engine.ddl.procedure.mysql;

import belf.migrate.api.util.QuoteType;
import belf.migrate.core.jdbc.FunctionModel;
import belf.migrate.core.jdbc.TypeModel;
import belf.migrate.engine.ddl.BaseDDLConvert;
import belf.migrate.plugin.mysql.antlr.MySqlParser;
import belf.migrate.plugin.mysql.antlr.MySqlParserBaseVisitor;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * MySql存储过程的的visitor遍历器，跟MySql函数的visitor极为相似,参考{@link belf.migrate.engine.ddl.function.mysql.MySqlFunctionVisitor}
 */
public class MySqlProcedureVisitor extends MySqlParserBaseVisitor<String> {
    //以下5个参数为构造参数
    private BaseDDLConvert ddlConvert;
    private String quote = "\"";
    private String schema;
    private Map<String, FunctionModel> funcMapping;
    private Map<String, TypeModel> typeMapping;

    //存储过程名称
    private String procedureName;
    //参数列表
    private List<MySqlParser.ProcedureParameterContext> parameters;

    // MySql函数定义里，参数申明在BEGIN..END之间，在达梦的函数定义里参数申明需要提到BEGIN之前
    private List<MySqlParser.DeclareVariableContext> variables;
    // BEGIN...END之间的函数定义语句
    private List<MySqlParser.ProcedureSqlStatementContext> procedureSqls;

    public MySqlProcedureVisitor(BaseDDLConvert ddlConvert,
                                 String schema,
                                 Map<String, FunctionModel> funcMapping,
                                 Map<String, TypeModel> typeMapping) {
        this.ddlConvert = ddlConvert;
        this.quote = QuoteType.DOUBLE_QUOTE.getValue();
        this.schema = schema;
        this.funcMapping = funcMapping;
        this.typeMapping = typeMapping;

        parameters = new ArrayList<>();
        variables = new ArrayList<>();
        procedureSqls = new ArrayList<>();
    }

    @Override
    public String visitCreateProcedure(MySqlParser.CreateProcedureContext ctx) {
        procedureName = ctx.fullId().getText().trim();
        procedureName = procedureName.replace("`", quote);
        if (procedureName.indexOf('.') == -1) {
            procedureName = quote + schema + quote + '.' + procedureName;
        }

        return visitChildren(ctx);
    }

    @Override
    public String visitProcedureParameter(MySqlParser.ProcedureParameterContext ctx) {
        if (BaseDDLConvert.hasAncestor("CreateProcedureContext", ctx)) {
            parameters.add(ctx);
        }
        return visitChildren(ctx);
    }

    @Override
    public String visitDeclareVariable(MySqlParser.DeclareVariableContext ctx) {
        variables.add(ctx);

        return visitChildren(ctx);
    }

    @Override
    public String visitProcedureSqlStatement(MySqlParser.ProcedureSqlStatementContext ctx) {
        // 排除子句重复查找
        if (!(BaseDDLConvert.hasAncestor("ProcedureSqlStatementContext", ctx))) {
            procedureSqls.add(ctx);
        }
        return visitChildren(ctx);
    }

    public String getProcedureName() {
        return procedureName;
    }

    public List<MySqlParser.ProcedureParameterContext> getParameters() {
        return parameters;
    }

    public List<MySqlParser.DeclareVariableContext> getVariables() {
        return variables;
    }

    public List<MySqlParser.ProcedureSqlStatementContext> getProcedureSqls() {
        return procedureSqls;
    }
}
